package com.yjc.drygoods.ware.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.yjc.common.constant.ExchangeDetailStatusEnum;
import com.yjc.common.constant.ExchangeStatusEnum;
import com.yjc.common.constant.PurchaseDetailStatusEnum;
import com.yjc.common.constant.PurchaseStatusEnum;
import com.yjc.common.utils.R;
import com.yjc.drygoods.ware.entity.*;
import com.yjc.drygoods.ware.exception.NotClearStockException;
import com.yjc.drygoods.ware.feign.ProductFeignService;
import com.yjc.drygoods.ware.service.*;
import com.yjc.drygoods.ware.to.SpuInfoTo;
import com.yjc.drygoods.ware.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yjc.common.utils.PageUtils;
import com.yjc.common.utils.Query;

import com.yjc.drygoods.ware.dao.ExchangeDao;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

@Slf4j
@Service("exchangeService")
public class ExchangeServiceImpl extends ServiceImpl<ExchangeDao, ExchangeEntity> implements ExchangeService {

    @Autowired
    ExchangeDetailService exchangeDetailService;

    @Autowired
    BatchesService batchesService;

    @Autowired
    ProductFeignService productFeignService;

    @Autowired
    WareSpuService wareSpuService;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<ExchangeEntity> page = this.page(
                new Query<ExchangeEntity>().getPage(params),
                new QueryWrapper<ExchangeEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public PageUtils queryPageUnreceiveList(Map<String, Object> params) {
        QueryWrapper<ExchangeEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("status", ExchangeDetailStatusEnum.CREATED.getCode())
                .or()
                .eq("status", ExchangeDetailStatusEnum.ASSIGNED.getCode());
        IPage<ExchangeEntity> page = this.page(
                new Query<ExchangeEntity>().getPage(params),
                queryWrapper
        );

        return new PageUtils(page);

    }

    @Transactional
    @Override
    public void saveMerge(ExMergeVo exMergeVo) {

        //要在判断采购需求是新建或者是已分配的情况下，才能够对其合并进采购单
        List<Long> items = exMergeVo.getItems();
        if (items != null && items.size() > 0) {
            List<ExchangeDetailEntity> exchangeDetails = exchangeDetailService.listByIds(items);
            //整单id
            //合并项集合
            Long exchangeId = exMergeVo.getExchangeId();
            //获取新建或已分配状态的采购需求
            List<ExchangeDetailEntity> collect = exchangeDetails.stream()
                    .filter(item -> item.getStatus() == ExchangeDetailStatusEnum.CREATED.getCode() || item.getStatus() == ExchangeDetailStatusEnum.ASSIGNED.getCode())
                    .collect(Collectors.toList());
            //还要判断是否有新建或者已分配状态的采购需求，没有就不创建采购单
            if (collect == null || collect.size() <= 0) {
                return;
            }
            if (exchangeId == null) {
                ExchangeEntity exchangeEntity = new ExchangeEntity();
                exchangeEntity.setUpdateTime(new Date());
                exchangeEntity.setCreateTime(new Date());
                exchangeEntity.setStatus(ExchangeDetailStatusEnum.CREATED.getCode());
                this.save(exchangeEntity);
                exchangeId = exchangeEntity.getId();
            }
            Long finalPurchaseId = exchangeId;


            List<ExchangeDetailEntity> resList = collect.stream()
                    .map(item -> {
                        item.setExchangeId(finalPurchaseId);
                        item.setStatus(ExchangeDetailStatusEnum.ASSIGNED.getCode());
                        item.setUpdateTime(new Date());
                        return item;
                    }).collect(Collectors.toList());
            exchangeDetailService.updateBatchById(resList);

            ExchangeEntity exchangeUpdateDate = new ExchangeEntity();
            exchangeUpdateDate.setUpdateTime(new Date());
            exchangeUpdateDate.setId(exchangeId);
            this.updateById(exchangeUpdateDate);
        }
    }

    @Override
    public void receiveExchange(List<Long> ids) {
        List<ExchangeEntity> exchangeEntities = this.baseMapper.selectBatchIds(ids);
        if (ids != null && ids.size() > 0) {
            List<ExchangeEntity> collect = exchangeEntities.stream()
                    .filter(item -> {
                        return item.getStatus() == ExchangeStatusEnum.CREATED.getCode() ||
                                item.getStatus() == ExchangeStatusEnum.ASSIGNED.getCode()
                                ? true : false;
                    })
                    .map(exchangeEntity -> {
                        exchangeEntity.setStatus(ExchangeStatusEnum.RECEIVED.getCode());
                        exchangeEntity.setUpdateTime(new Date());
                        return exchangeEntity;
                    }).collect(Collectors.toList());
            this.updateBatchById(collect);
            collect.forEach(i -> {
                List<ExchangeDetailEntity> exchangeDetailEntities = exchangeDetailService.listDetailByExchangeId(i.getId());
                List<ExchangeDetailEntity> collect1 = exchangeDetailEntities.stream()
                        .filter(item -> (item.getStatus() == ExchangeDetailStatusEnum.ASSIGNED.getCode()))
                        .map(ex -> {
                            ex.setStatus(ExchangeDetailStatusEnum.BUYING.getCode());
                            return ex;
                        }).collect(Collectors.toList());
                exchangeDetailService.updateBatchById(collect1);
            });

        }
    }

    @Override
    public void doneExchange(ExchangeDoneVo exchangeDoneVo) {
        //1.改变换货项的状态
        Boolean flage = true; //换货单状态
        List<ExchangeItemDoneVo> items = exchangeDoneVo.getItems();
        List<ExchangeDetailEntity> exchangeDetailEntities = new ArrayList<>();
        for (ExchangeItemDoneVo item : items) {
            Boolean singleSpuWare = wareSpuService.getSingleSpuWare(item.getAfterSpuId());
            if (singleSpuWare) {
                throw new NotClearStockException();
            }
            ExchangeDetailEntity exchangeDetail = exchangeDetailService.getById(item.getId());
            if (item.getStatus() == ExchangeDetailStatusEnum.BUYERROR.getCode()) {
                flage = false;
                exchangeDetail.setStatus(item.getStatus());
            } else if (item.getStatus() == PurchaseDetailStatusEnum.FINISHED.getCode()) {
                //3.将成功换货的进行入库
                //3.1设置换货需求状态
                exchangeDetail.setStatus(item.getStatus());
                //3.2设置该换货需求的置换后干货的数量
                if (item.getAfterSpuNum() == null) {
                    throw new RuntimeException("出错换货需求：" + item.getId() + "置换的干货数量不能为空");
                }
                exchangeDetail.setAfterSpuNum(item.getAfterSpuNum());
                //3.3设置该换货需求的置换后干货的进价
                if (item.getAfterSpuPrice() == null) {
                    throw new RuntimeException("出错换货需求：" + item.getId() + "置换的干货进价不能为空");
                }
                exchangeDetail.setAfterSpuPrice(item.getAfterSpuPrice());
                //3.4设置换货需求进货总价
                exchangeDetail.setAfterSpuTotalPrice(item.getAfterSpuPrice().multiply(new BigDecimal(item.getAfterSpuNum() + "")));
                //3.5设置换货需求更新时间
                exchangeDetail.setUpdateTime(new Date());
                //3.6设置该换货需求的置换后干货的id
                if (item.getAfterSpuId() - 10000L <= 0) {
                    throw new RuntimeException("出错换货需求：" + item.getId() + "请勿选择干货类别");
                }
                exchangeDetail.setAfterSpuId(item.getAfterSpuId() - 10000L);
                //3.7设置该换货需求的置换后干货的名称
                R r = productFeignService.spuInfo(exchangeDetail.getAfterSpuId());
                if (r.getCode() != 0) {
                    throw new RuntimeException("出错换货需求：" + item.getId() + "干货远程服务调用异常");
                }
                SpuInfoTo spuInfo = r.getData("spuInfo", new TypeReference<SpuInfoTo>() {
                });
                exchangeDetail.setAfterSpuName(spuInfo.getSpuName());
                //3.8设置该换货需求的置换后干货的批次
                BatchesEntity batches = batchesService.getSpuBatch(exchangeDetail.getAfterSpuId());
                if (batches != null) {
                    exchangeDetail.setAfterBatch(batches.getBatch() + 1);
                    //更新置换后的干货的库存信息
                } else {
                    //第一批次
                    exchangeDetail.setAfterBatch(1);

                }
                //4.更新置换后干货的库存信息
                wareSpuService.updateWareStock(exchangeDetail.getAfterSpuId(), exchangeDetail.getWareId(), exchangeDetail.getAfterSpuNum());
                //5.清除需换干货的库存数量并更新其在批次表中的信息
                wareSpuService.clearNeedExchangeSpuStock(exchangeDetail.getSpuId());
                BatchesEntity batchesEntity = new BatchesEntity();
                batchesEntity.setSpuId(exchangeDetail.getSpuId());
                batchesEntity.setSpuNum(0.0);
                batchesEntity.setUpdateTime(new Date());
                batchesService.updateById(batchesEntity);

            } else {
                throw new RuntimeException("出错换货需求：" + item.getId() + " 换货状态异常");
            }
//            exchangeDetail.setId(item.getItemId());
            exchangeDetailEntities.add(exchangeDetail);
        }
        exchangeDetailService.updateBatchById(exchangeDetailEntities);
        log.info("exchangeDetailEntities:{}", exchangeDetailEntities);


        //新增或更新置换后干货的批次信息
//        List<Long> resList = exchangeDetailEntities
//                .stream()
//                .filter(item -> item.getStatus() == PurchaseDetailStatusEnum.FINISHED.getCode())
//                .map(ExchangeDetailEntity::getAfterSpuId)
//                .collect(Collectors.toList());
//        log.info("PurchaseServiceImpl的resList:{}", resList);

        batchesService.saveOrUpdateBatchesToEx(exchangeDetailEntities);


        //3.改变换货单状态
        Long id = exchangeDoneVo.getId();
        ExchangeEntity exchangeEntity = new ExchangeEntity();
        exchangeEntity.setId(id);
        if (flage) {
            exchangeEntity.setStatus(ExchangeStatusEnum.FINISHED.getCode());
        } else {
            exchangeEntity.setStatus(ExchangeStatusEnum.HASEERROR.getCode());
        }
        for (ExchangeDetailEntity exchangeDetailEntity : exchangeDetailEntities) {
            if (exchangeDetailEntity.getStatus() == PurchaseDetailStatusEnum.FINISHED.getCode()) {
                exchangeEntity.setAmount(exchangeDetailEntity.getAfterSpuTotalPrice());
            }
        }
        exchangeEntity.setUpdateTime(new Date());
        this.updateById(exchangeEntity);
    }

    @Override
    public PageUtils getAllAssignedExchangeWithDetail(Map<String, Object> params) {
        QueryWrapper<ExchangeEntity> queryWrapper = new QueryWrapper<ExchangeEntity>()
                .eq("status", ExchangeStatusEnum.ASSIGNED.getCode());
        String userId = (String) params.get("userId");
        if (!StringUtils.isEmpty(userId)) {
            queryWrapper.eq("assignee_id", userId);
        }
        IPage<ExchangeEntity> page = this.page(
                new Query<ExchangeEntity>().getPage(params),
                queryWrapper
        );

        List<ExchangeEntity> exchangeList = page.getRecords();
        if (exchangeList == null || exchangeList.size() <= 0) {
            return new PageUtils(page);
        }

        List<ExchangeEntity> resList = exchangeList.stream()
                .map(item -> {
                    List<ExchangeDetailEntity> exchangeDetails = exchangeDetailService.list(new QueryWrapper<ExchangeDetailEntity>()
                            .eq("exchange_id", item.getId()).eq("status", ExchangeDetailStatusEnum.ASSIGNED.getCode()));
                    item.setItems(exchangeDetails);
                    return item;
                }).filter(item -> item.getItems() != null && item.getItems().size() > 0).collect(Collectors.toList());
        page.setRecords(resList);
        return new PageUtils(page);
    }

    @Override
    public PageUtils getAllHavedExchangeWithDetail(Map<String, Object> params) {
        QueryWrapper<ExchangeEntity> queryWrapper = new QueryWrapper<ExchangeEntity>()
                .eq("status", ExchangeStatusEnum.RECEIVED.getCode());
        String userId = (String) params.get("userId");
        if (!StringUtils.isEmpty(userId)) {
            queryWrapper.eq("assignee_id", userId);
        }
        IPage<ExchangeEntity> page = this.page(
                new Query<ExchangeEntity>().getPage(params),
                queryWrapper
        );

        List<ExchangeEntity> exchangeList = page.getRecords();
        if (exchangeList == null || exchangeList.size() <= 0) {
            return new PageUtils(page);
        }


        List<ExchangeEntity> resList = exchangeList.stream().map(itemTotal -> {
            List<ExchangeDetailEntity> exchangeDetails = exchangeDetailService.list(new QueryWrapper<ExchangeDetailEntity>()
                    .eq("exchange_id", itemTotal.getId()).eq("status", ExchangeDetailStatusEnum.BUYING.getCode()));
            if (exchangeDetails != null && exchangeDetails.size() > 0) {
                //设置完整三级路径加上自身的spuId
                List<ExchangeDetailEntity> exDetails = exchangeDetails.stream().map(item -> {
                    Long[] longs = {1L};
                    item.setCatelogPathWithSpu(longs);
                    return item;
                }).collect(Collectors.toList());
                itemTotal.setItems(exDetails);
            } else {
                itemTotal.setItems(exchangeDetails);
            }
            return itemTotal;
        }).filter(item -> item.getItems() != null && item.getItems().size() > 0).collect(Collectors.toList());
        page.setRecords(resList);
        return new PageUtils(page);

    }

}